//
// Created by wxd on 2025/8/10.
//

#include "Sphere.h"

#include "glm/ext/scalar_constants.hpp"

void Sphere::setCenter(glm::vec3 center) {
    m_Center = center;
}

void Sphere::setRadius(float radius) {
    m_Radius = radius;
}

void Sphere::setColor(glm::vec3 color) {
    m_Color = color;
}

void Sphere::setRasterLatitudes(unsigned int latitudes) {
    m_RasterLatitudes = latitudes;
}

void Sphere::setRasterLongitudes(unsigned int longitudes) {
    m_RasterLongitudes = longitudes;
}

glm::vec3 Sphere::getCenter() const {
    return m_Center;
}

glm::vec3 Sphere::getColor() const {
    return m_Color;
}

float Sphere::getRadius() const {
    return m_Radius;
}

unsigned int Sphere::getGirdVertices() const {
    return m_GridVertices;
}

unsigned int Sphere::getGridFaces() const {
    return m_GridFaces;
}

void Sphere::raster() {
    if (m_RasterLatitudes <= 1 || m_RasterLongitudes <= 1 || m_Radius <= 0.f) {
        return;
    }

    const auto latitudes = static_cast<float>(m_RasterLatitudes);
    const auto longitudes = static_cast<float>(m_RasterLongitudes);
    const auto unit_theta = 2.f * glm::pi<float>() / latitudes;
    const auto unit_phi = glm::pi<float>() / longitudes;

    // 生成顶点，法外，纹理坐标
    for (int i = 0; i <= m_RasterLatitudes; ++i) {
        for (int j = 0; j <= m_RasterLongitudes; ++j) {
            const auto ii = static_cast<float>(i);
            const auto jj = static_cast<float>(j);

            const auto phi = ii * unit_phi;
            const auto theta = jj * unit_theta;

            const auto sin_phi = glm::sin(phi);
            const auto cos_phi = glm::cos(phi);
            const auto sin_theta = glm::sin(theta);
            const auto cos_theta = glm::cos(theta);

            float y = m_Radius * cos_phi;
            float x = m_Radius * sin_phi * cos_theta;
            float z = m_Radius * sin_phi * sin_theta;

            // 顶点
            m_SphereVertices.emplace_back(x + m_Center.x, y + m_Center.y, z + m_Center.z);

            // 外法向量
            glm::vec3 n = glm::normalize(glm::vec3(x, y, z));
            m_SphereNormals.emplace_back(n.x, n.y, n.z);

            // 纹理坐标
            const float u = jj * 1.f / longitudes;
            const float v = 1.f - ii * 1.f / latitudes;
            m_SphereTexCoords.emplace_back(u, v);
        }
    }

    // 生成索引
    std::vector<unsigned int> indices;
    const unsigned int latVertexPeriod = m_RasterLongitudes + 1;
    for (int i = 0; i < m_RasterLatitudes; ++i) {
        for (int j = 0; j < m_RasterLongitudes; ++j) {
            const unsigned int p1 = i * latVertexPeriod + j;
            const unsigned int p2 = p1 + latVertexPeriod;
            const unsigned int p3 = p1 + 1;
            const unsigned int p4 = p2 + 1;

            m_SphereFaces.emplace_back(p1, p3, p2);
            m_SphereFaces.emplace_back(p3, p4, p2);
            indices.push_back(p1);
            indices.push_back(p3);
            indices.push_back(p2);

            indices.push_back(p3);
            indices.push_back(p4);
            indices.push_back(p2);
        }
    }

    m_IndicesCount = indices.size();
    m_GridFaces = m_SphereFaces.size() / 2;
    m_GridVertices = m_SphereVertices.size();

    getVAO()->bind();
    BaseGeometry::initEBO(indices, GL_STATIC_DRAW);
    BaseGeometry::setPos(0, m_SphereVertices);
    BaseGeometry::setUV(2, m_SphereTexCoords);
    BaseGeometry::setNormal(3, m_SphereNormals);
    getVAO()->unbind();
}







